package multiThreading;

//Has a Bug.
//Consumer thread does not exit
public class SynchronizedProducerConsumer
{
  public static void main(String args[])
  {
    Q q = new Q();
    new Producer(q);
    new Consumer(q);

    System.out.println("Press Control-C to stop.");
  }

  static class Consumer implements Runnable
  {
    Q q;

    Consumer(Q q)
    {
      this.q = q;
      new Thread(this, "Consumer").start();
    }

    public void run()
    {
      int i = 0;
      int last = -1;
      while (i < 2 && last != i)
      {
        q.get();
      }
    }
  }

  static class Producer implements Runnable
  {
    Q q;

    Producer(Q q)
    {
      this.q = q;
      new Thread(this, "Producer").start();
    }

    public void run()
    {
      int i = 0;

      while (i < 2)
      {
        q.put(i++);
      }
    }
  }

  static class Q
  {
    int n;
    boolean valueSet = false;
    
    int queueSize;
    
    synchronized int get()
    {
      while (!valueSet)
        try
        {
          wait();

        }
        catch (InterruptedException e)
        {
          System.out.println("InterruptedException caught");
        }

      System.out.println("Got: " + n);
      valueSet = false;
      notify();
      return n;
    }

    synchronized void put(int n)
    {
      while (valueSet)
        try
        {
          wait();
        }
        catch (InterruptedException e)
        {
          System.out.println("InterruptedException caught");
        }

      this.n = n;
      valueSet = true;
      System.out.println("Put: " + n);
      notify();
    }
  }
}
